/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Negative Shader API tests.
 *//*--------------------------------------------------------------------*/

#include "es3fNegativeShaderApiTests.hpp"
#include "es3fApiCase.hpp"
#include "gluShaderProgram.hpp"
#include "gluContextInfo.hpp"
#include "deUniquePtr.hpp"

#include "glwDefs.hpp"
#include "glwEnums.hpp"

using namespace glw; // GL types

namespace deqp
{
namespace gles3
{
namespace Functional
{

using tcu::TestLog;

static const char* vertexShaderSource		=	"#version 300 es\n"
												"void main (void)\n"
												"{\n"
												"	gl_Position = vec4(0.0);\n"
												"}\n\0";

static const char* fragmentShaderSource		=	"#version 300 es\n"
												"layout(location = 0) out mediump vec4 fragColor;"
												"void main (void)\n"
												"{\n"
												"	fragColor = vec4(0.0);\n"
												"}\n\0";

static const char* uniformTestVertSource	=	"#version 300 es\n"
												"uniform mediump vec4 vec4_v;\n"
												"uniform mediump mat4 mat4_v;\n"
												"void main (void)\n"
												"{\n"
												"	gl_Position = mat4_v * vec4_v;\n"
												"}\n\0";

static const char* uniformTestFragSource	=	"#version 300 es\n"
												"uniform mediump ivec4 ivec4_f;\n"
												"uniform mediump uvec4 uvec4_f;\n"
												"uniform sampler2D sampler_f;\n"
												"layout(location = 0) out mediump vec4 fragColor;"
												"void main (void)\n"
												"{\n"
												"	fragColor.xy = (vec4(uvec4_f) + vec4(ivec4_f)).xy;\n"
												"	fragColor.zw = texture(sampler_f, vec2(0.0, 0.0)).zw;\n"
												"}\n\0";

static const char* uniformBlockVertSource	=	"#version 300 es\n"
												"layout(shared) uniform Block { lowp float var; };\n"
												"void main (void)\n"
												"{\n"
												"	gl_Position = vec4(var);\n"
												"}\n\0";

NegativeShaderApiTests::NegativeShaderApiTests (Context& context)
	: TestCaseGroup(context, "shader", "Negative Shader API Cases")
{
}

NegativeShaderApiTests::~NegativeShaderApiTests (void)
{
}

void NegativeShaderApiTests::init (void)
{
	// Shader control commands

	ES3F_ADD_API_CASE(create_shader, "Invalid glCreateShader() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if shaderType is not an accepted value.");
			glCreateShader(-1);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(shader_source, "Invalid glShaderSource() usage",
		{
			// \note Shader compilation must be supported.

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glShaderSource(1, 0, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if count is less than 0.");
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);
			glShaderSource(shader, -1, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			GLuint program = glCreateProgram();
			glShaderSource(program, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(compile_shader, "Invalid glCompileShader() usage",
		{
			// \note Shader compilation must be supported.

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glCompileShader(9);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			GLuint program = glCreateProgram();
			glCompileShader(program);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
		});
	ES3F_ADD_API_CASE(delete_shader, "Invalid glDeleteShader() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glDeleteShader(9);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(shader_binary, "Invalid glShaderBinary() usage",
		{
			std::vector<deInt32> binaryFormats;
			getSupportedExtensions(GL_NUM_SHADER_BINARY_FORMATS, GL_SHADER_BINARY_FORMATS, binaryFormats);
			deBool shaderBinarySupported = !binaryFormats.empty();
			if (!shaderBinarySupported)
				m_log << TestLog::Message << "// Shader binaries not supported." << TestLog::EndMessage;
			else
				m_log << TestLog::Message << "// Shader binaries supported" << TestLog::EndMessage;

			GLuint shaders[2];
			shaders[0]		= glCreateShader(GL_VERTEX_SHADER);
			shaders[1]		= glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if binaryFormat is not an accepted value.");
			glShaderBinary(1, &shaders[0], -1, 0, 0);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			if (shaderBinarySupported)
			{
				m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if the data pointed to by binary does not match the format specified by binaryFormat.");
				const GLbyte data = 0x005F;
				glShaderBinary(1, &shaders[0], binaryFormats[0], &data, 1);
				expectError(GL_INVALID_VALUE);
				m_log << TestLog::EndSection;

				m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if more than one of the handles in shaders refers to the same type of shader, or GL_INVALID_VALUE due to invalid data pointer.");
				glShaderBinary(2, &shaders[0], binaryFormats[0], 0, 0);
				expectError(GL_INVALID_OPERATION, GL_INVALID_VALUE);
				m_log << TestLog::EndSection;
			}

			glDeleteShader(shaders[0]);
			glDeleteShader(shaders[1]);
		});
	ES3F_ADD_API_CASE(attach_shader, "Invalid glAttachShader() usage",
		{
			GLuint shader1 = glCreateShader(GL_VERTEX_SHADER);
			GLuint shader2 = glCreateShader(GL_VERTEX_SHADER);
			GLuint program = glCreateProgram();

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glAttachShader(shader1, shader1);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			glAttachShader(program, program);
			expectError(GL_INVALID_OPERATION);
			glAttachShader(shader1, program);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if either program or shader is not a value generated by OpenGL.");
			glAttachShader(program, -1);
			expectError(GL_INVALID_VALUE);
			glAttachShader(-1, shader1);
			expectError(GL_INVALID_VALUE);
			glAttachShader(-1, -1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is already attached to program.");
			glAttachShader(program, shader1);
			expectError(GL_NO_ERROR);
			glAttachShader(program, shader1);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if a shader of the same type as shader is already attached to program.");
			glAttachShader(program, shader2);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
			glDeleteShader(shader1);
			glDeleteShader(shader2);
		});
	ES3F_ADD_API_CASE(detach_shader, "Invalid glDetachShader() usage",
		{
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);
			GLuint program = glCreateProgram();

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if either program or shader is not a value generated by OpenGL.");
			glDetachShader(-1, shader);
			expectError(GL_INVALID_VALUE);
			glDetachShader(program, -1);
			expectError(GL_INVALID_VALUE);
			glDetachShader(-1, -1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glDetachShader(shader, shader);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			glDetachShader(program, program);
			expectError(GL_INVALID_OPERATION);
			glDetachShader(shader, program);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not attached to program.");
			glDetachShader(program, shader);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(link_program, "Invalid glLinkProgram() usage",
		{
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glLinkProgram(-1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glLinkProgram(shader);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is the currently active program object and transform feedback mode is active.");
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			deUint32					tfID;
			const char* tfVarying		= "gl_Position";

			glGenTransformFeedbacks		(1, &tfID);
			glGenBuffers				(1, &buf);

			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_NO_ERROR);

			glLinkProgram				(program.getProgram());
			expectError					(GL_INVALID_OPERATION);

			glEndTransformFeedback		();
			glDeleteTransformFeedbacks	(1, &tfID);
			glDeleteBuffers				(1, &buf);
			expectError					(GL_NO_ERROR);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(use_program, "Invalid glUseProgram() usage",
		{
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is neither 0 nor a value generated by OpenGL.");
			glUseProgram(-1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glUseProgram(shader);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback mode is active and not paused.");
			glu::ShaderProgram			program1(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			glu::ShaderProgram			program2(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			deUint32					tfID;
			const char* tfVarying		= "gl_Position";

			glGenTransformFeedbacks		(1, &tfID);
			glGenBuffers				(1, &buf);

			glUseProgram				(program1.getProgram());
			glTransformFeedbackVaryings	(program1.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program1.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_NO_ERROR);

			glUseProgram				(program2.getProgram());
			expectError					(GL_INVALID_OPERATION);

			glPauseTransformFeedback	();
			glUseProgram				(program2.getProgram());
			expectError					(GL_NO_ERROR);

			glEndTransformFeedback		();
			glDeleteTransformFeedbacks	(1, &tfID);
			glDeleteBuffers				(1, &buf);
			expectError					(GL_NO_ERROR);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(delete_program, "Invalid glDeleteProgram() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glDeleteProgram(-1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(validate_program, "Invalid glValidateProgram() usage",
		{
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glValidateProgram(-1);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glValidateProgram(shader);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_program_binary, "Invalid glGetProgramBinary() usage",
		{
			glu::ShaderProgram				program			(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			glu::ShaderProgram				programInvalid	(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, ""));
			GLenum							binaryFormat	= -1;
			GLsizei							binaryLength	= -1;
			GLint							binaryPtr		= -1;
			GLint							bufSize			= -1;
			GLint							linkStatus		= -1;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if bufSize is less than the size of GL_PROGRAM_BINARY_LENGTH for program.");
			glGetProgramiv		(program.getProgram(), GL_PROGRAM_BINARY_LENGTH,	&bufSize);
			expectError			(GL_NO_ERROR);
			glGetProgramiv		(program.getProgram(), GL_LINK_STATUS,				&linkStatus);
			m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage;
			m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage;
			expectError			(GL_NO_ERROR);

			glGetProgramBinary	(program.getProgram(), 0, &binaryLength, &binaryFormat, &binaryPtr);
			expectError			(GL_INVALID_OPERATION);
			if (bufSize > 0)
			{
				glGetProgramBinary	(program.getProgram(), bufSize-1, &binaryLength, &binaryFormat, &binaryPtr);
				expectError			(GL_INVALID_OPERATION);
			}
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if GL_LINK_STATUS for the program object is false.");
			glGetProgramiv		(programInvalid.getProgram(), GL_PROGRAM_BINARY_LENGTH,	&bufSize);
			expectError			(GL_NO_ERROR);
			glGetProgramiv		(programInvalid.getProgram(), GL_LINK_STATUS,			&linkStatus);
			m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage;
			m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage;
			expectError			(GL_NO_ERROR);

			glGetProgramBinary	(programInvalid.getProgram(), bufSize, &binaryLength, &binaryFormat, &binaryPtr);
			expectError			(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(program_binary, "Invalid glProgramBinary() usage",
		{
			glu::ShaderProgram		srcProgram		(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			GLuint					dstProgram		= glCreateProgram();
			GLuint					dummyShader		= glCreateShader(GL_VERTEX_SHADER);
			GLenum					binaryFormat	= -1;
			GLsizei					binaryLength	= -1;
			std::vector<deUint8>	binaryBuf;
			GLint					bufSize			= -1;
			GLint					linkStatus		= -1;

			glGetProgramiv		(srcProgram.getProgram(), GL_PROGRAM_BINARY_LENGTH,	&bufSize);
			glGetProgramiv		(srcProgram.getProgram(), GL_LINK_STATUS,			&linkStatus);
			m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage;
			m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage;

			TCU_CHECK(bufSize >= 0);

			if (bufSize > 0)
			{
				binaryBuf.resize(bufSize);
				glGetProgramBinary	(srcProgram.getProgram(), bufSize, &binaryLength, &binaryFormat, &binaryBuf[0]);
				expectError			(GL_NO_ERROR);

				m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not the name of an existing program object.");
				glProgramBinary		(dummyShader, binaryFormat, &binaryBuf[0], binaryLength);
				expectError			(GL_INVALID_OPERATION);
				m_log << TestLog::EndSection;

				m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if binaryFormat is not a value recognized by the implementation.");
				glProgramBinary		(dstProgram, -1, &binaryBuf[0], binaryLength);
				expectError			(GL_INVALID_ENUM);
				m_log << TestLog::EndSection;
			}

			glDeleteShader(dummyShader);
			glDeleteProgram(dstProgram);
		});
	ES3F_ADD_API_CASE(program_parameteri, "Invalid glProgramParameteri() usage",
		{
			GLuint	program	= glCreateProgram();

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of an existing program object.");
			glProgramParameteri		(0, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
			expectError				(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not GL_PROGRAM_BINARY_RETRIEVABLE_HINT.");
			glProgramParameteri		(program, -1, GL_TRUE);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if value is not GL_FALSE or GL_TRUE.");
			glProgramParameteri		(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, 2);
			expectError				(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
		});
	ES3F_ADD_API_CASE(gen_samplers, "Invalid glGenSamplers() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
			GLuint sampler;
			glGenSamplers	(-1, &sampler);
			expectError		(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(bind_sampler, "Invalid glBindSampler() usage",
		{
			int				maxTexImageUnits;
			GLuint			sampler;
			glGetIntegerv	(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTexImageUnits);
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if unit is greater than or equal to the value of GL_MAX_COMBIED_TEXTURE_IMAGE_UNITS.");
			glBindSampler	(maxTexImageUnits, sampler);
			expectError		(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not zero or a name previously returned from a call to glGenSamplers.");
			glBindSampler	(1, -1);
			expectError		(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler has been deleted by a call to glDeleteSamplers.");
			glDeleteSamplers(1, &sampler);
			glBindSampler	(1, sampler);
			expectError		(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(delete_samplers, "Invalid glDeleteSamplers() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
			glDeleteSamplers(-1, 0);
			expectError		(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_sampler_parameteriv, "Invalid glGetSamplerParameteriv() usage",
		{
			int				params	= -1;
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object returned from a previous call to glGenSamplers.");
			glGetSamplerParameteriv	(-1, GL_TEXTURE_MAG_FILTER, &params);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetSamplerParameteriv	(sampler, -1, &params);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});
	ES3F_ADD_API_CASE(get_sampler_parameterfv, "Invalid glGetSamplerParameterfv() usage",
		{
			float			params	= 0.0f;
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object returned from a previous call to glGenSamplers.");
			glGetSamplerParameterfv	(-1, GL_TEXTURE_MAG_FILTER, &params);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetSamplerParameterfv	(sampler, -1, &params);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});
	ES3F_ADD_API_CASE(sampler_parameteri, "Invalid glSamplerParameteri() usage",
		{
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers.");
			glSamplerParameteri		(-1, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.");
			glSamplerParameteri		(sampler, GL_TEXTURE_WRAP_S, -1);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});
	ES3F_ADD_API_CASE(sampler_parameteriv, "Invalid glSamplerParameteriv() usage",
		{
			int				params	= -1;
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers.");
			params = GL_CLAMP_TO_EDGE;
			glSamplerParameteriv	(-1, GL_TEXTURE_WRAP_S, &params);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.");
			params = -1;
			glSamplerParameteriv	(sampler, GL_TEXTURE_WRAP_S, &params);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});
	ES3F_ADD_API_CASE(sampler_parameterf, "Invalid glSamplerParameterf() usage",
		{
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers.");
			glSamplerParameterf		(-1, GL_TEXTURE_MIN_LOD, -1000.0f);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.");
			glSamplerParameterf		(sampler, GL_TEXTURE_WRAP_S, -1.0f);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});
	ES3F_ADD_API_CASE(sampler_parameterfv, "Invalid glSamplerParameterfv() usage",
		{
			float			params	= 0.0f;
			GLuint			sampler;
			glGenSamplers	(1, &sampler);

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers.");
			params = -1000.0f;
			glSamplerParameterfv	(-1, GL_TEXTURE_WRAP_S, &params);
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not.");
			params = -1.0f;
			glSamplerParameterfv	(sampler, GL_TEXTURE_WRAP_S, &params);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteSamplers(1, &sampler);
		});

	// Shader data commands

	ES3F_ADD_API_CASE(get_attrib_location, "Invalid glGetAttribLocation() usage",
		{
			GLuint programEmpty		= glCreateProgram();
			GLuint shader			= glCreateShader(GL_VERTEX_SHADER);

			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked.");
			glBindAttribLocation	(programEmpty, 0, "test");
			glGetAttribLocation		(programEmpty, "test");
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a program or shader object.");
			glUseProgram			(program.getProgram());
			glBindAttribLocation	(program.getProgram(), 0, "test");
			expectError				(GL_NO_ERROR);
			glGetAttribLocation		(program.getProgram(), "test");
			expectError				(GL_NO_ERROR);
			glGetAttribLocation		(-2, "test");
			expectError				(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetAttribLocation		(shader, "test");
			expectError				(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glUseProgram			(0);
			glDeleteShader			(shader);
			glDeleteProgram			(programEmpty);
		});
	ES3F_ADD_API_CASE(get_uniform_location, "Invalid glGetUniformLocation() usage",
		{
			GLuint programEmpty = glCreateProgram();
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);

			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked.");
			glGetUniformLocation(programEmpty, "test");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glUseProgram(program.getProgram());
			glGetUniformLocation(-2, "test");
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetAttribLocation(shader, "test");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteProgram(programEmpty);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(bind_attrib_location, "Invalid glBindAttribLocation() usage",
		{
			GLuint program = glCreateProgram();
			GLuint maxIndex = m_context.getContextInfo().getInt(GL_MAX_VERTEX_ATTRIBS);
			GLuint shader = glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			glBindAttribLocation(program, maxIndex, "test");
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if name starts with the reserved prefix \"gl_\".");
			glBindAttribLocation(program, maxIndex-1, "gl_test");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glBindAttribLocation(-1, maxIndex-1, "test");
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glBindAttribLocation(shader, maxIndex-1, "test");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(uniform_block_binding, "Invalid glUniformBlockBinding() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformBlockVertSource, uniformTestFragSource));

			glUseProgram	(program.getProgram());

			GLint			maxUniformBufferBindings;
			GLint			numActiveUniforms			= -1;
			GLint			numActiveBlocks				= -1;
			glGetIntegerv	(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
			glGetProgramiv	(program.getProgram(), GL_ACTIVE_UNIFORMS,			&numActiveUniforms);
			glGetProgramiv	(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCKS,	&numActiveBlocks);
			m_log << TestLog::Message << "// GL_MAX_UNIFORM_BUFFER_BINDINGS = " << maxUniformBufferBindings << TestLog::EndMessage;
			m_log << TestLog::Message << "// GL_ACTIVE_UNIFORMS = "				<< numActiveUniforms		<< TestLog::EndMessage;
			m_log << TestLog::Message << "// GL_ACTIVE_UNIFORM_BLOCKS = "		<< numActiveBlocks			<< TestLog::EndMessage;
			expectError		(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if uniformBlockIndex is not an active uniform block index of program.");
			glUniformBlockBinding(program.getProgram(), -1, 0);
			expectError(GL_INVALID_VALUE);
			glUniformBlockBinding(program.getProgram(), 5, 0);
			expectError(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if uniformBlockBinding is greater than or equal to the value of GL_MAX_UNIFORM_BUFFER_BINDINGS.");
			glUniformBlockBinding(program.getProgram(), maxUniformBufferBindings, 0);
			expectError(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object generated by the GL.");
			glUniformBlockBinding(-1, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;
		});

	// glUniform*f

	ES3F_ADD_API_CASE(uniformf_invalid_program, "Invalid glUniform{1234}f() usage",
		{
			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1f(-1, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform2f(-1, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform3f(-1, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform4f(-1, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformf_incompatible_type, "Invalid glUniform{1234}f() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1f(vec4_v, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform2f(vec4_v, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform3f(vec4_v, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform4f(vec4_v, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}f is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4.");
			glUseProgram(program.getProgram());
			glUniform4f(ivec4_f, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform4f(uvec4_f, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.");
			glUseProgram(program.getProgram());
			glUniform1f(sampler_f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformf_invalid_location, "Invalid glUniform{1234}f() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1f(-2, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform2f(-2, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform3f(-2, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);
			glUniform4f(-2, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1f(-1, 0.0f);
			expectError(GL_NO_ERROR);
			glUniform2f(-1, 0.0f, 0.0f);
			expectError(GL_NO_ERROR);
			glUniform3f(-1, 0.0f, 0.0f, 0.0f);
			expectError(GL_NO_ERROR);
			glUniform4f(-1, 0.0f, 0.0f, 0.0f, 0.0f);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// glUniform*fv

	ES3F_ADD_API_CASE(uniformfv_invalid_program, "Invalid glUniform{1234}fv() usage",
		{
			std::vector<GLfloat> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1fv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2fv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3fv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4fv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformfv_incompatible_type, "Invalid glUniform{1234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLfloat> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1fv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2fv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3fv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4fv(vec4_v, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}fv is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4.");
			glUseProgram(program.getProgram());
			glUniform4fv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4fv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.");
			glUseProgram(program.getProgram());
			glUniform1fv(sampler_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformfv_invalid_location, "Invalid glUniform{1234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			std::vector<GLfloat> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1fv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2fv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3fv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4fv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1fv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform2fv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform3fv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform4fv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformfv_invalid_count, "Invalid glUniform{1234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram			(program.getProgram());
			GLint vec4_v			= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			expectError(GL_NO_ERROR);

			if (vec4_v == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLfloat> data(8);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.");
			glUseProgram(program.getProgram());
			glUniform1fv(vec4_v, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2fv(vec4_v, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3fv(vec4_v, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4fv(vec4_v, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// glUniform*i

	ES3F_ADD_API_CASE(uniformi_invalid_program, "Invalid glUniform{1234}i() usage",
		{
			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1i(-1, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(-1, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(-1, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(-1, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformi_incompatible_type, "Invalid glUniform{1234}i() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1i(ivec4_f, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(ivec4_f, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(ivec4_f, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(ivec4_f, 0, 0, 0, 0);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type unsigned int, uvec2, uvec3, uvec4, or an array of these.");
			glUseProgram(program.getProgram());
			glUniform1i(uvec4_f, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(uvec4_f, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(uvec4_f, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(uvec4_f, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type float, vec2, vec3, or vec4.");
			glUseProgram(program.getProgram());
			glUniform1i(vec4_v, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(vec4_v, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(vec4_v, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(vec4_v, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformi_invalid_location, "Invalid glUniform{1234}i() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1i(-2, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(-2, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(-2, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(-2, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1i(-1, 0);
			expectError(GL_NO_ERROR);
			glUniform2i(-1, 0, 0);
			expectError(GL_NO_ERROR);
			glUniform3i(-1, 0, 0, 0);
			expectError(GL_NO_ERROR);
			glUniform4i(-1, 0, 0, 0, 0);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// glUniform*iv

	ES3F_ADD_API_CASE(uniformiv_invalid_program, "Invalid glUniform{1234}iv() usage",
		{
			std::vector<GLint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1iv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformiv_incompatible_type, "Invalid glUniform{1234}iv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1iv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(ivec4_f, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type float, vec2, vec3, or vec4.");
			glUseProgram(program.getProgram());
			glUniform1iv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type unsigned int, uvec2, uvec3 or uvec4.");
			glUseProgram(program.getProgram());
			glUniform1iv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformiv_invalid_location, "Invalid glUniform{1234}iv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			std::vector<GLint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1iv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1iv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform2iv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform3iv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform4iv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformiv_invalid_count, "Invalid glUniform{1234}iv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram			(program.getProgram());
			GLint ivec4_f			= glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4
			expectError(GL_NO_ERROR);

			if (ivec4_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLint> data(8);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.");
			glUseProgram(program.getProgram());
			glUniform1iv(ivec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2iv(ivec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3iv(ivec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4iv(ivec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// glUniform{1234}ui

	ES3F_ADD_API_CASE(uniformui_invalid_program, "Invalid glUniform{234}ui() usage",
		{
			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1ui(-1, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2ui(-1, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3ui(-1, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4ui(-1, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformui_incompatible_type, "Invalid glUniform{1234}ui() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1ui(uvec4_f, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2ui(uvec4_f, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3ui(uvec4_f, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4ui(uvec4_f, 0, 0, 0, 0);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type int, ivec2, ivec3, ivec4, or an array of these.");
			glUseProgram(program.getProgram());
			glUniform1ui(ivec4_f, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2ui(ivec4_f, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3ui(ivec4_f, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4ui(ivec4_f, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type float, vec2, vec3, or vec4.");
			glUseProgram(program.getProgram());
			glUniform1ui(vec4_v, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2ui(vec4_v, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3ui(vec4_v, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4ui(vec4_v, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.");
			glUseProgram(program.getProgram());
			glUniform1ui(sampler_f, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformui_invalid_location, "Invalid glUniform{1234}ui() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1i(-2, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform2i(-2, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform3i(-2, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			glUniform4i(-2, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1i(-1, 0);
			expectError(GL_NO_ERROR);
			glUniform2i(-1, 0, 0);
			expectError(GL_NO_ERROR);
			glUniform3i(-1, 0, 0, 0);
			expectError(GL_NO_ERROR);
			glUniform4i(-1, 0, 0, 0, 0);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// glUniform{1234}uiv

	ES3F_ADD_API_CASE(uniformuiv_invalid_program, "Invalid glUniform{234}uiv() usage",
		{
			std::vector<GLuint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniform1uiv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(-1, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniformuiv_incompatible_type, "Invalid glUniform{1234}uiv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			GLint vec4_v	= glGetUniformLocation(program.getProgram(), "vec4_v");	// vec4
			GLint ivec4_f	= glGetUniformLocation(program.getProgram(), "ivec4_f");	// ivec4
			GLint uvec4_f	= glGetUniformLocation(program.getProgram(), "uvec4_f");	// uvec4
			GLint sampler_f	= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLuint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniform1uiv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(uvec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(uvec4_f, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type float, vec2, vec3, or vec4.");
			glUseProgram(program.getProgram());
			glUniform1uiv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(vec4_v, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type int, ivec2, ivec3 or ivec4.");
			glUseProgram(program.getProgram());
			glUniform1uiv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(ivec4_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.");
			glUseProgram(program.getProgram());
			glUniform1uiv(sampler_f, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformuiv_invalid_location, "Invalid glUniform{1234}uiv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			std::vector<GLuint> data(4);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniform1uiv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(-2, 1, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniform1uiv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform2uiv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform3uiv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			glUniform4uiv(-1, 1, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniformuiv_invalid_count, "Invalid glUniform{1234}uiv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram			(program.getProgram());
			int uvec4_f				= glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4
			expectError(GL_NO_ERROR);

			if (uvec4_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLuint> data(8);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.");
			glUseProgram(program.getProgram());
			glUniform1uiv(uvec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform2uiv(uvec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform3uiv(uvec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniform4uiv(uvec4_f, 2, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});


	// glUniformMatrix*fv

	ES3F_ADD_API_CASE(uniform_matrixfv_invalid_program, "Invalid glUniformMatrix{234}fv() usage",
		{
			std::vector<GLfloat> data(16);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object.");
			glUseProgram(0);
			glUniformMatrix2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUniformMatrix2x3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix2x4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(uniform_matrixfv_incompatible_type, "Invalid glUniformMatrix{234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram			(program.getProgram());
			GLint mat4_v			= glGetUniformLocation(program.getProgram(), "mat4_v");	// mat4
			GLint sampler_f			= glGetUniformLocation(program.getProgram(), "sampler_f");	// sampler2D
			expectError(GL_NO_ERROR);

			if (mat4_v == -1 || sampler_f == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLfloat> data(16);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.");
			glUseProgram(program.getProgram());
			glUniformMatrix2fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);

			glUniformMatrix2x3fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x2fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix2x4fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x2fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x4fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x3fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.");
			glUseProgram(program.getProgram());
			glUniformMatrix2fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUniformMatrix2x3fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x2fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix2x4fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x2fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x4fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x3fv(sampler_f, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniform_matrixfv_invalid_location, "Invalid glUniformMatrix{234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);

			std::vector<GLfloat> data(16);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.");
			glUseProgram(program.getProgram());
			glUniformMatrix2fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUniformMatrix2x3fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x2fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix2x4fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x2fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x4fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x3fv(-2, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUseProgram(program.getProgram());
			glUniformMatrix2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);

			glUniformMatrix2x3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix3x2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix2x4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix4x2fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix3x4fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			glUniformMatrix4x3fv(-1, 1, GL_FALSE, &data[0]);
			expectError(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(uniform_matrixfv_invalid_count, "Invalid glUniformMatrix{234}fv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));

			glUseProgram			(program.getProgram());
			GLint mat4_v			= glGetUniformLocation(program.getProgram(), "mat4_v"); // mat4
			expectError(GL_NO_ERROR);

			if (mat4_v == -1)
			{
				m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage;
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");
			}

			std::vector<GLfloat> data(32);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.");
			glUseProgram(program.getProgram());
			glUniformMatrix2fv(mat4_v, 2, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3fv(mat4_v, 2, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4fv(mat4_v, 2, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);

			glUniformMatrix2x3fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x2fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix2x4fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x2fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix3x4fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			glUniformMatrix4x3fv(mat4_v, 1, GL_FALSE, &data[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glUseProgram(0);
		});

	// Transform feedback

	ES3F_ADD_API_CASE(gen_transform_feedbacks, "Invalid glGenTransformFeedbacks() usage",
		{
			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
			GLuint id;
			glGenTransformFeedbacks(-1, &id);
			expectError(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(bind_transform_feedback, "Invalid glBindTransformFeedback() usage",
		{
			GLuint						tfID[2];
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			const char* tfVarying		= "gl_Position";

			glGenBuffers				(1, &buf);
			glGenTransformFeedbacks		(2, tfID);

			m_log << tcu::TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_TRANSFORM_FEEDBACK.");
			glBindTransformFeedback(-1, tfID[0]);
			expectError(GL_INVALID_ENUM);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the transform feedback operation is active on the currently bound transform feedback object, and is not paused.");
			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID[0]);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_NO_ERROR);

			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID[1]);
			expectError					(GL_INVALID_OPERATION);

			glEndTransformFeedback		();
			expectError					(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glUseProgram				(0);
			glDeleteBuffers				(1, &buf);
			glDeleteTransformFeedbacks	(2, tfID);
			expectError					(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(delete_transform_feedbacks, "Invalid glDeleteTransformFeedbacks() usage",
		{
			GLuint id;
			glGenTransformFeedbacks(1, &id);

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
			glDeleteTransformFeedbacks(-1, &id);
			expectError(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			glDeleteTransformFeedbacks(1, &id);
		});
	ES3F_ADD_API_CASE(begin_transform_feedback, "Invalid glBeginTransformFeedback() usage",
		{
			GLuint						tfID[2];
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			const char* tfVarying		= "gl_Position";

			glGenBuffers				(1, &buf);
			glGenTransformFeedbacks		(2, tfID);

			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID[0]);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			expectError					(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_ENUM is generated if primitiveMode is not one of GL_POINTS, GL_LINES, or GL_TRIANGLES.");
			glBeginTransformFeedback	(-1);
			expectError					(GL_INVALID_ENUM);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback is already active.");
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_NO_ERROR);
			glBeginTransformFeedback	(GL_POINTS);
			expectError					(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if any binding point used in transform feedback mode does not have a buffer object bound.");
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_INVALID_OPERATION);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if no binding points would be used because no program object is active.");
			glUseProgram				(0);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_INVALID_OPERATION);
			glUseProgram				(program.getProgram());
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if no binding points would be used because the active program object has specified no varying variables to record.");
			glTransformFeedbackVaryings	(program.getProgram(), 0, 0, GL_INTERLEAVED_ATTRIBS);
			glBeginTransformFeedback	(GL_TRIANGLES);
			expectError					(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glEndTransformFeedback		();
			glDeleteBuffers				(1, &buf);
			glDeleteTransformFeedbacks	(2, tfID);
			expectError					(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(pause_transform_feedback, "Invalid glPauseTransformFeedback() usage",
		{
			GLuint						tfID[2];
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			const char* tfVarying		= "gl_Position";

			glGenBuffers				(1, &buf);
			glGenTransformFeedbacks		(2, tfID);

			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID[0]);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			expectError					(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is paused.");
			glPauseTransformFeedback	();
			expectError					(GL_INVALID_OPERATION);
			glBeginTransformFeedback	(GL_TRIANGLES);
			glPauseTransformFeedback	();
			expectError					(GL_NO_ERROR);
			glPauseTransformFeedback	();
			expectError					(GL_INVALID_OPERATION);
			m_log << tcu::TestLog::EndSection;

			glEndTransformFeedback		();
			glDeleteBuffers				(1, &buf);
			glDeleteTransformFeedbacks	(2, tfID);
			expectError					(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(resume_transform_feedback, "Invalid glResumeTransformFeedback() usage",
		{
			GLuint						tfID[2];
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			const char* tfVarying		= "gl_Position";

			glGenBuffers				(1, &buf);
			glGenTransformFeedbacks		(2, tfID);

			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID[0]);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			expectError					(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is not paused.");
			glResumeTransformFeedback	();
			expectError					(GL_INVALID_OPERATION);
			glBeginTransformFeedback	(GL_TRIANGLES);
			glResumeTransformFeedback	();
			expectError					(GL_INVALID_OPERATION);
			glPauseTransformFeedback	();
			glResumeTransformFeedback	();
			expectError					(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glEndTransformFeedback		();
			glDeleteBuffers				(1, &buf);
			glDeleteTransformFeedbacks	(2, tfID);
			expectError					(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(end_transform_feedback, "Invalid glEndTransformFeedback() usage",
		{
			GLuint						tfID;
			glu::ShaderProgram			program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			deUint32					buf;
			const char* tfVarying		= "gl_Position";

			glGenBuffers				(1, &buf);
			glGenTransformFeedbacks		(1, &tfID);

			glUseProgram				(program.getProgram());
			glTransformFeedbackVaryings	(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			glLinkProgram				(program.getProgram());
			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tfID);
			glBindBuffer				(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
			glBufferData				(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
			glBindBufferBase			(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
			expectError					(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback is not active.");
			glEndTransformFeedback		();
			expectError					(GL_INVALID_OPERATION);
			glBeginTransformFeedback	(GL_TRIANGLES);
			glEndTransformFeedback		();
			expectError					(GL_NO_ERROR);
			m_log << tcu::TestLog::EndSection;

			glDeleteBuffers				(1, &buf);
			glDeleteTransformFeedbacks	(1, &tfID);
			expectError					(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(get_transform_feedback_varying, "Invalid glGetTransformFeedbackVarying() usage",
		{
			GLuint					tfID;
			glu::ShaderProgram		program			(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			glu::ShaderProgram		programInvalid	(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, ""));
			const char* tfVarying	= "gl_Position";
			int						maxTransformFeedbackVaryings = 0;

			GLsizei					length;
			GLsizei					size;
			GLenum					type;
			char					name[32];

			glGenTransformFeedbacks			(1, &tfID);

			glTransformFeedbackVaryings		(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			expectError						(GL_NO_ERROR);
			glLinkProgram					(program.getProgram());
			expectError						(GL_NO_ERROR);

			glBindTransformFeedback			(GL_TRANSFORM_FEEDBACK, tfID);
			expectError						(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object.");
			glGetTransformFeedbackVarying	(-1, 0, 32, &length, &size, &type, &name[0]);
			expectError						(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater or equal to the value of GL_TRANSFORM_FEEDBACK_VARYINGS.");
			glGetProgramiv					(program.getProgram(), GL_TRANSFORM_FEEDBACK_VARYINGS, &maxTransformFeedbackVaryings);
			glGetTransformFeedbackVarying	(program.getProgram(), maxTransformFeedbackVaryings, 32, &length, &size, &type, &name[0]);
			expectError						(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION or GL_INVALID_VALUE is generated program has not been linked.");
			glGetTransformFeedbackVarying	(programInvalid.getProgram(), 0, 32, &length, &size, &type, &name[0]);
			expectError						(GL_INVALID_OPERATION, GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			glDeleteTransformFeedbacks		(1, &tfID);
			expectError						(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(transform_feedback_varyings, "Invalid glTransformFeedbackVaryings() usage",
		{
			GLuint					tfID;
			glu::ShaderProgram		program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
			const char* tfVarying	= "gl_Position";
			GLint					maxTransformFeedbackSeparateAttribs = 0;

			glGenTransformFeedbacks			(1, &tfID);
			expectError						(GL_NO_ERROR);

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object.");
			glTransformFeedbackVaryings		(0, 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
			expectError						(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if bufferMode is GL_SEPARATE_ATTRIBS and count is greater than GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.");
			glGetIntegerv					(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxTransformFeedbackSeparateAttribs);
			glTransformFeedbackVaryings		(program.getProgram(), maxTransformFeedbackSeparateAttribs+1, &tfVarying, GL_SEPARATE_ATTRIBS);
			expectError						(GL_INVALID_VALUE);
			m_log << tcu::TestLog::EndSection;

			glDeleteTransformFeedbacks		(1, &tfID);
			expectError						(GL_NO_ERROR);
		});
}

} // Functional
} // gles3
} // deqp
